import importlib

from typing import Any, Dict, Callable

from apscheduler.triggers.base import BaseTrigger

from ctaf_core.ctaf_resources.ctaf_settings import CTAFsettings
from ctaf_core.ctaf_utils.config_process_util import load_quartz_task_settings, exp_to_trigger_instance
from ctaf_core.quartz_task_bundle.quartz_task_data import QuartzTaskData


class ScheduledInstanceContainer:

    def __init__(self):
        self.quartz_task_setting_filename: str = CTAFsettings.get_setting("quartzTaskSettingFilename")
        # key:value of this Dict is quartz_task_name: {"task_class_path":bus_service_class_path, "task_method_name":quartz_task_method_name,"task_cron":cron_exp}
        self.quartz_task_settings: Dict[str,Dict[str, Any]] = load_quartz_task_settings(self.quartz_task_setting_filename)

        # key:value of this Dict is quartz_task_name:quartz_task_instance_data
        self.__quartz_task_instances: Dict[str, QuartzTaskData] = {}
        self.add_task_instance_from_settings(self.quartz_task_settings)

    def init_quartz_task(self, quartz_task_name: str, quartz_task_setting: Dict):
        task_class_path = quartz_task_setting["task_class_path"]
        task_method_name = quartz_task_setting["task_method_name"]
        task_trigger_type = quartz_task_setting["task_trigger_type"]
        trigger_exp = quartz_task_setting["trigger_exp"]

        module_name, class_name = task_class_path.rsplit('.', 1)
        module = importlib.import_module(module_name)
        quartz_task_class = getattr(module, class_name)
        quartz_task_instance = quartz_task_class()
        if hasattr(quartz_task_instance, task_method_name):
            task_instance_method: Callable = getattr(quartz_task_instance, task_method_name)
            task_trigger: BaseTrigger = exp_to_trigger_instance(task_trigger_type, trigger_exp)
            self.__quartz_task_instances[quartz_task_name] = QuartzTaskData(task_instance_method, task_trigger)

    def add_task_instance_from_settings(self, quartz_task_settings: Dict[str, Dict[str, str]]):
        for quartz_task_name, quartz_task_setting in quartz_task_settings.items():
            self.init_quartz_task(quartz_task_name,quartz_task_setting)

    def get_quartz_task_by_name(self, quartz_task_name: str)->QuartzTaskData:
        return self.__quartz_task_instances[quartz_task_name]

    def get_all_quartz_task_names(self)->[]:
        return self.__quartz_task_instances.keys()

class ScheduledInstanceContainerFactory:
    __scheduled_instance_container = None

    @staticmethod
    def get_scheduled_instance_container() -> ScheduledInstanceContainer:
        if ScheduledInstanceContainerFactory.__scheduled_instance_container is None:
            ScheduledInstanceContainerFactory.__scheduled_instance_container = ScheduledInstanceContainer()
        return ScheduledInstanceContainerFactory.__scheduled_instance_container